﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace testUI
{
    public partial class Form1_r1 : Form
    {
        // METHODS IMPORTED FROM DLL
        // For JSTEG, F3, F4, F5
        // under x86, int = long = Int32
        public const String DLLPATH = "tools\\tools.dll";
        [DllImport(DLLPATH, EntryPoint = "jstege", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 jstege(StringBuilder input_name, StringBuilder output_name, StringBuilder msg, Int32 msglen, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "jstegd", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 jstegd(StringBuilder input_name, StringBuilder output_name, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f3e", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f3e(StringBuilder input_name, StringBuilder output_name, StringBuilder msg, Int32 msglen, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f3d", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f3d(StringBuilder input_name, StringBuilder output_name, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f4e", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f4e(StringBuilder input_name, StringBuilder output_name, StringBuilder msg, Int32 msglen, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f4d", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f4d(StringBuilder input_name, StringBuilder output_name, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f5e", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f5e(StringBuilder input_name, StringBuilder output_name, Int32 k, StringBuilder msg, Int32 msglen, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "f5d", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 f5d(StringBuilder input_name, StringBuilder output_name, Int32 k, Int32 seed);
        [DllImport(DLLPATH, EntryPoint = "changeQuality", CallingConvention = CallingConvention.Cdecl)]
        public static extern Int32 changeQuality(StringBuilder input_name, StringBuilder output_name, Int32 quality);

        // GUI

        private string inpath1 = "";
        private string outpath1 = "";
        private string inpath2 = "";

        public Form1_r1()
        {
            InitializeComponent();
        }

        private void btn_picsel2_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "JPEG File|*.jpg|All files (*.*)|*.*";
            openFileDialog1.Title = "Select a JPEG File";
            openFileDialog1.CheckFileExists = true;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.inpath2 = openFileDialog1.FileName;
                Console.WriteLine("Load image: " + this.inpath2);
                Image img = Image.FromFile(inpath2);
                Image bitmap = new Bitmap(img);
                img.Dispose();
                this.pbox_in2.Image = bitmap;
            }
        }

        private void btn_exit2_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btn_exit1_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btn_picsel1_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "Images(*.BMP;*.JPG;*.TIF)|*.BMP;*.JPG;*.TIF|All files (*.*)|*.*";
            openFileDialog1.Title = "Select an Image";
            openFileDialog1.InitialDirectory = "D:\\IJG";
            openFileDialog1.CheckFileExists = true;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.inpath1 = openFileDialog1.FileName;
                Console.WriteLine("Load image: " + this.inpath1);
                Image img = Image.FromFile(inpath1);
                Image bitmap = new Bitmap(img);
                img.Dispose();
                this.pbox_in1.Image = bitmap;
            }
        }

        private void btn_msgsel_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = "Text File|*.txt|All files (*.*)|*.*";
            openFileDialog1.Title = "Select a text file";
            openFileDialog1.InitialDirectory = "D:\\UCID.JPG";
            openFileDialog1.CheckFileExists = true;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                Console.WriteLine("Load text: " + openFileDialog1.FileName);
                StreamReader sr = new StreamReader(openFileDialog1.FileName);
                String s = sr.ReadToEnd();
                sr.Close();
                this.tbx_msg1.Text = s;
            }
        }

        private void btn_outsel1_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "JPEG File|*.jpg";
            saveFileDialog1.Title = "Save as JPEG File";
            saveFileDialog1.OverwritePrompt = true;
            saveFileDialog1.InitialDirectory = "D:\\IJG";

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.outpath1 = saveFileDialog1.FileName;
                Console.WriteLine("Save to: " + this.outpath1);
            }

        }

        private void btn_ok1_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Use " + this.gbox_1.Name.ToString() + " to encode");
            Int32 seed, f5k, quality;
            try
            {
                seed = Convert.ToInt32(this.tbx_rand1.Text);
                f5k = Convert.ToInt32(this.tbx_f5k1.Text);
                quality = Convert.ToInt32(this.tbx_qf1.Text);
            }
            catch (FormatException)
            {
                MessageBox.Show("Invalid number format.");
                return;
            }
            if ((f5k < 1) || (f5k > 5) || (quality > 100) || (quality <= 0))
            {
                MessageBox.Show("Invalid value.");
                return;
            }
            string tempfname = System.IO.Path.GetTempFileName() + ".jpg";
            if (this.inpath1.Equals(""))
            {
                MessageBox.Show("No input file.");
                return;
            }
            if (this.outpath1.Equals(""))
            {
                MessageBox.Show("No output file.");
                return;
            }
            StringBuilder msg = new StringBuilder(this.tbx_msg1.Text);
            Int32 msglen = msg.Length;
            StringBuilder iname = new StringBuilder(this.inpath1);
            StringBuilder oname = new StringBuilder(tempfname);
            long retval = -1;
            // Quality Factor
            retval = changeQuality(iname, oname, quality);
            if (retval != 0)
                MessageBox.Show("Cannot convert quality!");
            iname = new StringBuilder(tempfname);
            oname = new StringBuilder(this.outpath1);
            retval = -1;
            switch (this.gbox_1.Name)
            {
                case "Jsteg":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = jstege(iname, oname, msg, msglen, seed);
                    break;
                case "F3":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f3e(iname, oname, msg, msglen, seed);
                    break;
                case "F4":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f4e(iname, oname, msg, msglen, seed);
                    break;
                case "F5":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f5e(iname, oname, f5k, msg, msglen, seed);
                    break;
                default:
                    MessageBox.Show("Method not selected.");
                    return;

            }
            Console.WriteLine("End time : " + DateTime.Now);
            Console.WriteLine("Return value = " + retval);
            MessageBox.Show("Finished!");
        }

        private void rbtn_jsteg1_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_1.Name = "Jsteg";
            this.tbx_f5k1.Enabled = false;
        }

        private void rbtn_f31_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_1.Name = "F3";
            this.tbx_f5k1.Enabled = false;
        }

        private void rbtn_f41_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_1.Name = "F4";
            this.tbx_f5k1.Enabled = false;
        }

        private void rbtn_f51_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_1.Name = "F5";
            this.tbx_f5k1.Enabled = true;
        }

        private void rbtn_jsteg2_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_2.Name = "Jsteg";
            this.tbx_f5k2.Enabled = false;
        }

        private void rbtn_f32_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_2.Name = "F3";
            this.tbx_f5k2.Enabled = false;
        }

        private void rbtn_f42_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_2.Name = "F4";
            this.tbx_f5k2.Enabled = false;
        }

        private void rbtn_f52_CheckedChanged(object sender, EventArgs e)
        {
            this.gbox_2.Name = "F5";
            this.tbx_f5k2.Enabled = true;
        }

        private void btn_ok2_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Use " + this.gbox_2.Name.ToString() + " to decode");
            Int32 seed, f5k;
            try
            {
                seed = Convert.ToInt32(this.tbx_rand2.Text);
                f5k = Convert.ToInt32(this.tbx_f5k2.Text);
            }
            catch (FormatException)
            {
                MessageBox.Show("Invalid number format.");
                return;
            }
            if ((f5k < 1) || (f5k > 5))
            {
                MessageBox.Show("Invalid value.");
                return;
            }
            string tempfname = System.IO.Path.GetTempFileName();
            if (this.inpath2.Equals(""))
            {
                MessageBox.Show("No input file.");
                return;
            }
            StringBuilder iname = new StringBuilder(this.inpath2);
            StringBuilder oname = new StringBuilder(tempfname);
            long retval = -1;
            this.tbx_msg2.Clear();
            switch (this.gbox_2.Name)
            {
                case "Jsteg":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = jstegd(iname, oname, seed);
                    break;
                case "F3":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f3d(iname, oname, seed);
                    break;
                case "F4":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f4d(iname, oname, seed);
                    break;
                case "F5":
                    Console.WriteLine("Begin time : " + DateTime.Now);
                    retval = f5d(iname, oname, f5k, seed);
                    break;
                default:
                    MessageBox.Show("Method not selected.");
                    return;

            }
            Console.WriteLine("End time : " + DateTime.Now);
            Console.WriteLine("Return value = " + retval);
            // READ OUTPUT FILE
            if (retval > 0)
            {
                StreamReader sr = new StreamReader(tempfname);
                String s = sr.ReadToEnd();
                sr.Close();
                this.tbx_msg2.Text = s;
            }
            MessageBox.Show("Finished!");
        }
    }

}
